#include <chat.h>
#include <config.h>
#include <server.h>

#include <vector>
#include <algorithm>

#include <sqlite3.h>

using namespace std;
using namespace Chat;

extern vector<User> userList;

StateRet ServerGroupChat(const Message& msg, int sockfd)
{
    int ret;

    /*声明数据库变量*/
    sqlite3*      db;
    sqlite3_stmt* stmt;
    const char*   tail;
    /*声明sql语句存储变量*/
    char sql[512]{};

    /*消息发送缓冲区*/
    char buf[MAX_LINE]{};
    /*消息内容*/
    Message message{msg};
    strncpy(message.content, msg.content, strlen(msg.content));
    strncpy(message.sendName, msg.sendName, strlen(msg.sendName));
    strncpy(message.recvName, msg.recvName, strlen(msg.recvName));
    strncpy(message.msgTime, msg.msgTime, strlen(msg.msgTime));

    /*查看在线用户*/
    /*除了自己无人在线*/
    if (userList.empty()) {
        /*改变消息类型为RESULT*/
        message.msgType = MessageType::RESULT;
        strcpy(message.content, stateMsg(StateRet::ALL_NOT_ONLINE).c_str());
        memset(buf, 0, MAX_LINE);
        memcpy(buf, &message, sizeof(message));
        send(sockfd, buf, sizeof(buf), 0);
        return StateRet::ALL_NOT_ONLINE;
    }   // if
    /*向所有在线用户发送消息*/
    else {
        for (const auto& iter : userList) {
            if (strcmp(iter.userName, message.sendName) != 0) {
                memset(buf, 0, MAX_LINE);
                memcpy(buf, &message, sizeof(message));
                send(iter.sockfd, buf, sizeof(buf), 0);
            }   // else
        }
        /*（1）打开数据库*/
        ret = sqlite3_open(DB_NAME.c_str(), &db);
        if (ret != SQLITE_OK) {
            printf("unable open database!\n");
            return StateRet::FAILED;
        }   // if
        /*（2）执行插入操作*/
        memset(sql, 0, sizeof(sql));
        sprintf(sql,
                "insert into Message(msgType , sendName , recvName , content , msgTime)\
				values(%d,'%s','%s','%s', '%s');",
                (int)message.msgType,
                message.sendName,
                message.recvName,
                message.content,
                message.msgTime);

        ret = sqlite3_prepare(db, sql, strlen(sql), &stmt, &tail);
        if (ret != SQLITE_OK) {
            ret = sqlite3_step(stmt);
            sqlite3_finalize(stmt);
            sqlite3_close(db);
            return StateRet::FAILED;
        }   // if

        /*（3）顺利插入*/
        ret = sqlite3_step(stmt);
        sqlite3_finalize(stmt);
        sqlite3_close(db);
        /*群聊处理成功*/
        return StateRet::SUCCESS;
    }
}

StateRet ServerPersonalChat(const Message& msg, int sockfd)
{
    int ret;

    /*声明数据库变量*/
    sqlite3*      db;
    sqlite3_stmt* stmt;
    const char*   tail;
    /*声明sql语句存储变量*/
    char sql[512];

    /*消息发送缓冲区*/
    char buf[MAX_LINE];
    /*消息内容*/
    Message message{};
    strcpy(message.sendName, msg.sendName);
    strcpy(message.recvName, msg.recvName);
    message.msgType = msg.msgType;
    /*消息发送对象和接收对象相同*/
    if (strcmp(msg.sendName, msg.recvName) == 0) {
        printf("消息不能发送到自己！\n");
        /*改变消息类型为RESULT*/
        message.msgType = MessageType::RESULT;
        strcpy(message.content, stateMsg(StateRet::MESSAGE_SELF).c_str());
        memset(buf, 0, MAX_LINE);
        memcpy(buf, &message, sizeof(message));
        send(sockfd, buf, sizeof(buf), 0);
        return StateRet::MESSAGE_SELF;
    }   // if

    /*查找接收信息用户*/
    auto iter =
        find_if(userList.cbegin(),
                userList.cend(),
                [&message](const User& x) { return strcmp(x.userName, message.recvName) == 0; });
    if (iter == userList.cend()) {
        printf("该用户不在线！\n");
        /*改变消息类型为RESULT*/
        message.msgType = MessageType::RESULT;
        strcpy(message.content, stateMsg(StateRet::ID_NOT_ONLINE).c_str());
        memset(buf, 0, MAX_LINE);
        memcpy(buf, &message, sizeof(message));
        send(sockfd, buf, sizeof(buf), 0);
        return StateRet::ID_NOT_ONLINE;
    }
    else {
        strcpy(message.content, msg.content);
        strcpy(message.msgTime, msg.msgTime);
        memset(buf, 0, MAX_LINE);
        memcpy(buf, &message, sizeof(message));
        printf("向用户%s发送\n", iter->userName);
        send(iter->sockfd, buf, sizeof(buf), 0);

        /*写到数据库*/
        /*（1）打开数据库*/
        ret = sqlite3_open(DB_NAME.c_str(), &db);
        if (ret != SQLITE_OK) {
            printf("unable open database!\n");
            return StateRet::FAILED;
        }   // if
        /*（2）执行插入操作*/
        memset(sql, 0, sizeof(sql));
        sprintf(sql,
                "insert into Message(msgType , sendName , recvName , content , msgTime)\
				values(%d,'%s','%s','%s', '%s');",
                message.msgType,
                message.sendName,
                message.recvName,
                message.content,
                message.msgTime);
        printf("%s\n", sql);

        ret = sqlite3_prepare(db, sql, strlen(sql), &stmt, &tail);
        if (ret != SQLITE_OK) {
            ret = sqlite3_step(stmt);
            sqlite3_finalize(stmt);
            sqlite3_close(db);
            return StateRet::FAILED;
        }   // if

        /*（3）顺利插入*/
        ret = sqlite3_step(stmt);
        sqlite3_finalize(stmt);
        sqlite3_close(db);
        /*私聊处理成功*/
        return StateRet::SUCCESS;
    }
}


void ServerEnterChat(int* fd)
{
    int      n, sockfd;
    StateRet ret;
    User     user{};
    /*消息发送缓冲区*/
    char buf[MAX_LINE]{};
    /*消息内容*/
    Message message{};

    sockfd = *fd;

    while (1) {   // 接收用户发送的消息
        n = recv(sockfd, buf, sizeof(buf) + 1, 0);
        // printf("ServerEnterChat n = %d\n" , n);
        if (n == 0) {
            // 关闭当前描述符
            close(sockfd);
            return;
        }   // if
        else {
            memcpy(&message, buf, sizeof(buf));

            switch (message.msgType) {
            case MessageType::GROUP_CHAT: {
                printf("来自%s的群聊请求！\n", message.sendName);
                printf("%s 发送群消息: %s\n", message.sendName, message.content);
                /*转到群聊处理函数*/
                ret = ServerGroupChat(message, sockfd);
                printf("群聊：%s\n", stateMsg(ret).c_str());
                break;
            }

            case MessageType::PERSONAL_CHAT: {
                printf("来自%s的私聊请求！\n", message.sendName);
                printf("%s向%s发送私聊消息: %s\n",
                       message.sendName,
                       message.recvName,
                       message.content);
                /*转到私聊处理函数*/
                ret = ServerPersonalChat(message, sockfd);
                printf("私聊：%s\n", stateMsg(ret));
                break;
            }

            case MessageType::VIEW_USER_LIST: {
                printf("来自%s的查看在线用户列表请求！\n", message.sendName);
                /*转到查看在线用户列表处理函数*/
                // ret = ServerViewUserList(&message, sockfd);
                printf("查看在线列表：%s\n", stateMsg(ret));
                break;
            }

            case MessageType::VIEW_RECORDS: {
                printf("来自%s的查看聊天记录的请求！\n", message.sendName);
                // ret = ServerViewRecords(&message, sockfd);
                printf("查看聊天记录：%s\n", stateMsg(ret));
                break;
            }

            case MessageType::EXIT: {
                /*用户退出聊天室*/
                printf("用户%s退出聊天室！\n", message.sendName);
                memset(&user, 0, sizeof(user));
                strcpy(user.userName, message.sendName);
                auto item = std::find_if(userList.cbegin(),
                                         userList.cend(),
                                         [&user](User x)
                                         { return (strcmp(x.userName, user.userName) == 0); });
                if (item != userList.cend()) {
                    userList.erase(item);
                }

                close(sockfd);
                return;
            }

            default:
                break;
            }
        }
    }
}
